home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sprite.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  34KB  |  1,157 lines

  1. #include "driver.h"
  2.  
  3. #define SWAP(X,Y) { int temp = X; X = Y; Y = temp; }
  4.  
  5. /*
  6.     Games currently using the Sprite Manager:
  7.         Sega System16
  8.         Blood Brothers
  9.         Shoot Out
  10.         Ninja Gaiden
  11.  
  12.     The Sprite Manager provides a service that would be difficult or impossible using drawgfx.
  13.     It allows sprite-to-sprite priority to be orthogonal to sprite-to-tilemap priority.
  14.  
  15.     The sprite manager also abstract a nice chunk of generally useful functionality.
  16.  
  17.     Drivers making use of Sprite Manager will NOT necessarily be any faster than traditional
  18.     drivers using drawgfx.
  19.  
  20.     Currently supported features include:
  21.     - sprite layering order, FRONT_TO_BACK / BACK_TO_FRONT (can be easily switched from a driver)
  22.     - priority masking (needed for Gaiden, Blood Brothers, and surely many others)
  23.       this allows sprite-to-sprite priority to be orthogonal to sprite-to-layer priority.
  24.     - resource tracking (sprite_init and sprite_close must be called by mame.c)
  25.     - flickering sprites
  26.     - offscreen sprite skipping
  27.     - palette usage tracking
  28.     - screen orientation/clipping (preliminary!  rotation isn't working properly with
  29.         SPRITE_TYPE_UNPACK and SPRITE_TYPE_STACK, yet)
  30.     - support for graphics that aren't pre-rotated (i.e. System16)
  31.  
  32. There are three sprite types that a sprite_list may use.  With all three sprite types, sprite->x and sprite->y
  33. are screenwise coordinates for the topleft pixel of a sprite, and sprite->total_width, sprite->total_width is the
  34. sprite size in screen coordinates - the "footprint" of the sprite on the screen.  sprite->line_offset indicates
  35. offset from one logical row of sprite pen data to the next.
  36.  
  37.     SPRITE_TYPE_UNPACK
  38.         Often, it is possible to unpack a sprite at it's "largest" size, and draw a subset of it.
  39.         Some games (i.e. Ninja Gaiden) have a size sprite attribute that defines a recursive arrangement
  40.         of smaller (typically 8x8 pixel) tiles, i.e:
  41.  
  42.             0 1 4 5
  43.             2 3 6 7
  44.             8 9 c d
  45.             a b e f
  46.  
  47.         If the above is the largest configuration, SPRITE_TYPE_UNPACK lets you specify tiny sprites (0,1,2,3,...)
  48.         medium size sprites (0123, 4567, 89ab), or large sprites (the entire configuration: 012452367...)
  49.  
  50.         To unpack the sprite 1436 in the above example, the following fields would be used:
  51.  
  52.         size of sprite to be drawn
  53.             sprite->total_width = 16
  54.             sprite->total_height = 16
  55.  
  56.         size of largest possible sprite:
  57.             sprite->tile_width = 32
  58.             sprite->tile_height = 32
  59.  
  60.         relative offset of the sprite to be drawn:
  61.             sprite->x_offset = 8
  62.             sprite->y_offset = 0
  63.  
  64.     SPRITE_TYPE_STACK
  65.         Sometimes a predetermined arrangement is not possible.  SPRITE_TYPE_STACK will draw a series of sprites,
  66.         stacking them from top to bottom, and then from left to right.  This is used by Blood Brothers.
  67.         The Sprite Manager will handle flipping and positioning of individual tiles.
  68.         sprite->total_width must be a multiple of sprite->tile_width
  69.         sprite->total_height must be a multiple of sprite->tile_height
  70.  
  71.     SPRITE_TYPE_ZOOM
  72.         line_offset is pen skip to next line; tile_width and tile_height are logical sprite dimensions
  73.         The sprite will be stretched to fit total_width, total_height, shrinking or magnifying as needed
  74.  
  75.     TBA:
  76.     - GfxElement-oriented field-setting macros
  77.     - cocktail support
  78.     - "special" pen (hides pixels of previously drawn sprites) - for MCR games, Mr. Do's Castle, etc.
  79.     - end-of-line marking pen (needed for Altered Beast, ESWAT)
  80. */
  81.  
  82. static int orientation, screen_width, screen_height;
  83. static int screen_clip_left, screen_clip_top, screen_clip_right, screen_clip_bottom;
  84. unsigned char *screen_baseaddr;
  85. int screen_line_offset;
  86.  
  87. static struct sprite_list *first_sprite_list = NULL; /* used for resource tracking */
  88. static int FlickeringInvisible;
  89.  
  90. static UINT16 *shade_table;
  91.  
  92. static void sprite_order_setup( struct sprite_list *sprite_list, int *first, int *last, int *delta ){
  93.     if( sprite_list->flags&SPRITE_LIST_FRONT_TO_BACK ){
  94.         *delta = -1;
  95.         *first = sprite_list->num_sprites-1;
  96.         *last = 0;
  97.     }
  98.     else {
  99.         *delta = 1;
  100.         *first = 0;
  101.         *last = sprite_list->num_sprites-1;
  102.     }
  103. }
  104.  
  105. /*********************************************************************
  106.  
  107.     The mask buffer is a dynamically allocated resource
  108.     it is recycled each frame.  Using this technique reduced the runttime
  109.     memory requirements of the Gaiden from 512k (worst case) to approx 6K.
  110.  
  111.     Sprites use offsets instead of pointers directly to the mask data, since it
  112.     is potentially reallocated.
  113.  
  114. *********************************************************************/
  115. static unsigned char *mask_buffer = NULL;
  116. static int mask_buffer_size = 0; /* actual size of allocated buffer */
  117. static int mask_buffer_used = 0;
  118.  
  119. static void mask_buffer_reset( void ){
  120.     mask_buffer_used = 0;
  121. }
  122. static void mask_buffer_dispose( void ){
  123.     free( mask_buffer );
  124.     mask_buffer = NULL;
  125.     mask_buffer_size = 0;
  126. }
  127. static long mask_buffer_alloc( long size ){
  128.     long result = mask_buffer_used;
  129.     long req_size = mask_buffer_used + size;
  130.     if( req_size>mask_buffer_size ){
  131.         mask_buffer = realloc( mask_buffer, req_size );
  132.         mask_buffer_size = req_size;
  133.         logerror("increased sprite mask buffer size to %d bytes.\n", mask_buffer_size );
  134.         if( !mask_buffer ) logerror("Error! insufficient memory for mask_buffer_alloc\n" );
  135.     }
  136.     mask_buffer_used = req_size;
  137.     memset( &mask_buffer[result], 0x00, size ); /* clear it */
  138.     return result;
  139. }
  140.  
  141. #define BLIT \
  142. if( sprite->flags&SPRITE_FLIPX ){ \
  143.     source += screenx + flipx_adjust; \
  144.     for( y=y1; y<y2; y++ ){ \
  145.         for( x=x1; x<x2; x++ ){ \
  146.             if( OPAQUE(-x) ) dest[x] = COLOR(-x); \
  147.         } \
  148.         source += source_dy; dest += blit.line_offset; \
  149.         NEXTLINE \
  150.     } \
  151. } \
  152. else { \
  153.     source -= screenx; \
  154.     for( y=y1; y<y2; y++ ){ \
  155.         for( x=x1; x<x2; x++ ){ \
  156.             if( OPAQUE(x) ) dest[x] = COLOR(x); \
  157.             \
  158.         } \
  159.         source += source_dy; dest += blit.line_offset; \
  160.         NEXTLINE \
  161.     } \
  162. }
  163.  
  164. static struct {
  165.     int transparent_pen;
  166.     int clip_left, clip_right, clip_top, clip_bottom;
  167.     unsigned char *baseaddr;
  168.     int line_offset;
  169.     int write_to_mask;
  170.     int origin_x, origin_y;
  171. } blit;
  172.  
  173. static void do_blit_unpack( const struct sprite *sprite ){
  174.     const unsigned short *pal_data = sprite->pal_data;
  175.     int transparent_pen = blit.transparent_pen;
  176.  
  177.     int screenx = sprite->x - blit.origin_x;
  178.     int screeny = sprite->y - blit.origin_y;
  179.     int x1 = screenx;
  180.     int y1 = screeny;
  181.     int x2 = x1 + sprite->total_width;
  182.     int y2 = y1 + sprite->total_height;
  183.     int flipx_adjust = sprite->total_width-1;
  184.  
  185.     int source_dy;
  186.     const unsigned char *baseaddr = sprite->pen_data;
  187.     const unsigned char *source;
  188.     unsigned char *dest;
  189.     int x,y;
  190.  
  191.     source = baseaddr + sprite->line_offset*sprite->y_offset + sprite->x_offset;
  192.  
  193.     if( x1<blit.clip_left )        x1 = blit.clip_left;
  194.     if( y1<blit.clip_top )        y1 = blit.clip_top;
  195.     if( x2>blit.clip_right )    x2 = blit.clip_right;
  196.     if( y2>blit.clip_bottom )    y2 = blit.clip_bottom;
  197.  
  198.     if( x1<x2 && y1<y2 ){
  199.         dest = blit.baseaddr + y1*blit.line_offset;
  200.         if( sprite->flags&SPRITE_FLIPY ){
  201.             source_dy = -sprite->line_offset;
  202.             source += (y2-1-screeny)*sprite->line_offset;
  203.         }
  204.         else {
  205.             source_dy = sprite->line_offset;
  206.             source += (y1-screeny)*sprite->line_offset;
  207.         }
  208.         if( blit.write_to_mask ){
  209.             #define OPAQUE(X) (source[X]!=transparent_pen)
  210.             #define COLOR(X) 0xff
  211.             #define NEXTLINE
  212.             BLIT
  213.             #undef OPAQUE
  214.             #undef COLOR
  215.             #undef NEXTLINE
  216.         }
  217.         else if( sprite->mask_offset>=0 ){ /* draw a masked sprite */
  218.             const unsigned char *mask = &mask_buffer[sprite->mask_offset] +
  219.                 (y1-sprite->y)*sprite->total_width-sprite->x;
  220.             #define OPAQUE(X) (mask[x]==0 && source[X]!=transparent_pen)
  221.             #define COLOR(X) (pal_data[source[X]])
  222.             #define NEXTLINE mask+=sprite->total_width;
  223.             BLIT
  224.             #undef OPAQUE
  225.             #undef COLOR
  226.             #undef NEXTLINE
  227.         }
  228.         else if( sprite->flags&SPRITE_TRANSPARENCY_THROUGH ){
  229.             int color = Machine->pens[palette_transparent_color];
  230.             #define OPAQUE(X) (dest[x]==color && source[X]!=transparent_pen)
  231.             #define COLOR(X) (pal_data[source[X]])
  232.             #define NEXTLINE
  233.             BLIT
  234.             #undef OPAQUE
  235.             #undef COLOR
  236.             #undef NEXTLINE
  237.         }
  238.         else if( pal_data ){
  239.             #define OPAQUE(X) (source[X]!=transparent_pen)
  240.             #define COLOR(X) (pal_data[source[X]])
  241.             #define NEXTLINE
  242.             BLIT
  243.             #undef OPAQUE
  244.             #undef COLOR
  245.             #undef NEXTLINE
  246.         }
  247.     }
  248. }
  249.  
  250. static void do_blit_stack( const struct sprite *sprite ){
  251.     const unsigned short *pal_data = sprite->pal_data;
  252.     int transparent_pen = blit.transparent_pen;
  253.     int flipx_adjust = sprite->tile_width-1;
  254.  
  255.     int xoffset, yoffset;
  256.     int screenx, screeny;
  257.     int x1, y1, x2, y2;
  258.     int x,y;
  259.  
  260.     int source_dy;
  261.     const unsigned char *baseaddr = sprite->pen_data;
  262.     const unsigned char *source;
  263.     unsigned char *dest;
  264.  
  265.     for( xoffset =0; xoffset<sprite->total_width; xoffset+=sprite->tile_width ){
  266.         for( yoffset=0; yoffset<sprite->total_height; yoffset+=sprite->tile_height ){
  267.             source = baseaddr;
  268.             screenx = sprite->x - blit.origin_x;
  269.             screeny = sprite->y - blit.origin_y;
  270.  
  271.             if( sprite->flags & SPRITE_FLIPX ){
  272.                 screenx += sprite->total_width - sprite->tile_width - xoffset;
  273.             }
  274.             else {
  275.                 screenx += xoffset;
  276.             }
  277.  
  278.             if( sprite->flags & SPRITE_FLIPY ){
  279.                 screeny += sprite->total_height - sprite->tile_height - yoffset;
  280.             }
  281.             else {
  282.                 screeny += yoffset;
  283.             }
  284.  
  285.             x1 = screenx;
  286.             y1 = screeny;
  287.             x2 = x1 + sprite->tile_width;
  288.             y2 = y1 + sprite->tile_height;
  289.  
  290.             if( x1<blit.clip_left )        x1 = blit.clip_left;
  291.             if( y1<blit.clip_top )        y1 = blit.clip_top;
  292.             if( x2>blit.clip_right )    x2 = blit.clip_right;
  293.             if( y2>blit.clip_bottom )    y2 = blit.clip_bottom;
  294.  
  295.             if( x1<x2 && y1<y2 ){
  296.                 dest = blit.baseaddr + y1*blit.line_offset;
  297.  
  298.                 if( sprite->flags&SPRITE_FLIPY ){
  299.                     source_dy = -sprite->line_offset;
  300.                     source += (y2-1-screeny)*sprite->line_offset;
  301.                 }
  302.                 else {
  303.                     source_dy = sprite->line_offset;
  304.                     source += (y1-screeny)*sprite->line_offset;
  305.                 }
  306.  
  307.                 if( blit.write_to_mask ){
  308.                     #define OPAQUE(X) (source[X]!=transparent_pen)
  309.                     #define COLOR(X) 0xff
  310.                     #define NEXTLINE
  311.                     BLIT
  312.                     #undef OPAQUE
  313.                     #undef COLOR
  314.                     #undef NEXTLINE
  315.                 }
  316.                 else if( sprite->mask_offset>=0 ){ /* draw a masked sprite */
  317.                     const unsigned char *mask = &mask_buffer[sprite->mask_offset] +
  318.                         (y1-sprite->y)*sprite->total_width-sprite->x;
  319.                     #define OPAQUE(X) (mask[x]==0 && source[X]!=transparent_pen)
  320.                     #define COLOR(X) (pal_data[source[X]])
  321.                     #define NEXTLINE mask+=sprite->total_width;
  322.                     BLIT
  323.                     #undef OPAQUE
  324.                     #undef COLOR
  325.                     #undef NEXTLINE
  326.                 }
  327.                 else if( sprite->flags&SPRITE_TRANSPARENCY_THROUGH ){
  328.                     int color = Machine->pens[palette_transparent_color];
  329.                     #define OPAQUE(X) (dest[x]==color && source[X]!=transparent_pen)
  330.                     #define COLOR(X) (pal_data[source[X]])
  331.                     #define NEXTLINE
  332.                     BLIT
  333.                     #undef OPAQUE
  334.                     #undef COLOR
  335.                     #undef NEXTLINE
  336.                 }
  337.                 else if( pal_data ){
  338.                     #define OPAQUE(X) (source[X]!=transparent_pen)
  339.                     #define COLOR(X) (pal_data[source[X]])
  340.                     #define NEXTLINE
  341.                     BLIT
  342.                     #undef OPAQUE
  343.                     #undef COLOR
  344.                     #undef NEXTLINE
  345.                 }
  346.             } /* not totally clipped */
  347.             baseaddr += sprite->tile_height*sprite->line_offset;
  348.         } /* next yoffset */
  349.     } /* next xoffset */
  350. }
  351.  
  352.  
  353.  
  354. static void do_blit_zoom( const struct sprite *sprite ){
  355.     /*    assumes SPRITE_LIST_RAW_DATA flag is set */
  356.  
  357.     int x1,x2, y1,y2, dx,dy;
  358.     int xcount0 = 0, ycount0 = 0;
  359.  
  360.     if( sprite->flags & SPRITE_FLIPX ){
  361.         x2 = sprite->x;
  362.         x1 = x2+sprite->total_width;
  363.         dx = -1;
  364.         if( x2<blit.clip_left ) x2 = blit.clip_left;
  365.         if( x1>blit.clip_right ){
  366.             xcount0 = (x1-blit.clip_right)*sprite->tile_width;
  367.             x1 = blit.clip_right;
  368.         }
  369.         if( x2>=x1 ) return;
  370.         x1--; x2--;
  371.     }
  372.     else {
  373.         x1 = sprite->x;
  374.         x2 = x1+sprite->total_width;
  375.         dx = 1;
  376.         if( x1<blit.clip_left ){
  377.             xcount0 = (blit.clip_left-x1)*sprite->tile_width;
  378.             x1 = blit.clip_left;
  379.         }
  380.         if( x2>blit.clip_right ) x2 = blit.clip_right;
  381.         if( x1>=x2 ) return;
  382.     }
  383.     if( sprite->flags & SPRITE_FLIPY ){
  384.         y2 = sprite->y;
  385.         y1 = y2+sprite->total_height;
  386.         dy = -1;
  387.         if( y2<blit.clip_top ) y2 = blit.clip_top;
  388.         if( y1>blit.clip_bottom ){
  389.             ycount0 = (y1-blit.clip_bottom)*sprite->tile_height;
  390.             y1 = blit.clip_bottom;
  391.         }
  392.         if( y2>=y1 ) return;
  393.         y1--; y2--;
  394.     }
  395.     else {
  396.         y1 = sprite->y;
  397.         y2 = y1+sprite->total_height;
  398.         dy = 1;
  399.         if( y1<blit.clip_top ){
  400.             ycount0 = (blit.clip_top-y1)*sprite->tile_height;
  401.             y1 = blit.clip_top;
  402.         }
  403.         if( y2>blit.clip_bottom ) y2 = blit.clip_bottom;
  404.         if( y1>=y2 ) return;
  405.     }
  406.  
  407.     if(!(sprite->flags & (SPRITE_SHADOW | SPRITE_PARTIAL_SHADOW)))
  408.     {
  409.         const unsigned char *pen_data = sprite->pen_data;
  410.         const unsigned short *pal_data = sprite->pal_data;
  411.         int x,y;
  412.         unsigned char pen;
  413.         int pitch = blit.line_offset*dy;
  414.         unsigned char *dest = blit.baseaddr + blit.line_offset*y1;
  415.         int ycount = ycount0;
  416.  
  417.         if( orientation & ORIENTATION_SWAP_XY ){ /* manually rotate the sprite graphics */
  418.             int xcount = xcount0;
  419.             for( x=x1; x!=x2; x+=dx ){
  420.                 const unsigned char *source;
  421.                 unsigned char *dest1;
  422.  
  423.                 ycount = ycount0;
  424.                 while( xcount>=sprite->total_width ){
  425.                     xcount -= sprite->total_width;
  426.                     pen_data+=sprite->line_offset;
  427.                 }
  428.                 source = pen_data;
  429.                 dest1 = &dest[x];
  430.                 for( y=y1; y!=y2; y+=dy ){
  431.                     while( ycount>=sprite->total_height ){
  432.                         ycount -= sprite->total_height;
  433.                         source ++;
  434.                     }
  435.                     pen = *source;
  436.                     if( pen==0xff ) goto skip1; /* marker for right side of sprite; needed for AltBeast, ESwat */
  437. /*                    if( pen==10 ) *dest1 = shade_table[*dest1];
  438.                     else */if( pen ) *dest1 = pal_data[pen];
  439.                     ycount+= sprite->tile_height;
  440.                     dest1 += pitch;
  441.                 }
  442. skip1:
  443.                 xcount += sprite->tile_width;
  444.             }
  445.         }
  446.         else {
  447.             for( y=y1; y!=y2; y+=dy ){
  448.                 int xcount = xcount0;
  449.                 const unsigned char *source;
  450.                 while( ycount>=sprite->total_height ){
  451.                     ycount -= sprite->total_height;
  452.                     pen_data += sprite->line_offset;
  453.                 }
  454.                 source = pen_data;
  455.                 for( x=x1; x!=x2; x+=dx ){
  456.                     while( xcount>=sprite->total_width ){
  457.                         xcount -= sprite->total_width;
  458.                         source++;
  459.                     }
  460.                     pen = *source;
  461.                     if( pen==0xff ) goto skip; /* marker for right side of sprite; needed for AltBeast, ESwat */
  462. /*                    if( pen==10 ) dest[x] = shade_table[dest[x]];
  463.                     else */if( pen ) dest[x] = pal_data[pen];
  464.                     xcount += sprite->tile_width;
  465.                 }
  466. skip:
  467.                 ycount += sprite->tile_height;
  468.                 dest += pitch;
  469.             }
  470.         }
  471.     }
  472.     else if(sprite->flags & SPRITE_PARTIAL_SHADOW)
  473.     {
  474.         const unsigned char *pen_data = sprite->pen_data;
  475.         const unsigned short *pal_data = sprite->pal_data;
  476.         int x,y;
  477.         unsigned char pen;
  478.         int pitch = blit.line_offset*dy;
  479.         unsigned char *dest = blit.baseaddr + blit.line_offset*y1;
  480.         int ycount = ycount0;
  481.  
  482.         if( orientation & ORIENTATION_SWAP_XY ){ /* manually rotate the sprite graphics */
  483.             int xcount = xcount0;
  484.             for( x=x1; x!=x2; x+=dx ){
  485.                 const unsigned char *source;
  486.                 unsigned char *dest1;
  487.  
  488.                 ycount = ycount0;
  489.                 while( xcount>=sprite->total_width ){
  490.                     xcount -= sprite->total_width;
  491.                     pen_data+=sprite->line_offset;
  492.                 }
  493.                 source = pen_data;
  494.                 dest1 = &dest[x];
  495.                 for( y=y1; y!=y2; y+=dy ){
  496.                     while( ycount>=sprite->total_height ){
  497.                         ycount -= sprite->total_height;
  498.                         source ++;
  499.                     }
  500.                     pen = *source;
  501.                     if( pen==0xff ) goto skip6; /* marker for right side of sprite; needed for AltBeast, ESwat */
  502.                     if( pen==sprite->shadow_pen ) *dest1 = shade_table[*dest1];
  503.                     else if( pen ) *dest1 = pal_data[pen];
  504.                     ycount+= sprite->tile_height;
  505.                     dest1 += pitch;
  506.                 }
  507. skip6:
  508.                 xcount += sprite->tile_width;
  509.             }
  510.         }
  511.         else {
  512.             for( y=y1; y!=y2; y+=dy ){
  513.                 int xcount = xcount0;
  514.                 const unsigned char *source;
  515.                 while( ycount>=sprite->total_height ){
  516.                     ycount -= sprite->total_height;
  517.                     pen_data += sprite->line_offset;
  518.                 }
  519.                 source = pen_data;
  520.                 for( x=x1; x!=x2; x+=dx ){
  521.                     while( xcount>=sprite->total_width ){
  522.                         xcount -= sprite->total_width;
  523.                         source++;
  524.                     }
  525.                     pen = *source;
  526.                     if( pen==0xff ) goto skip5; /* marker for right side of sprite; needed for AltBeast, ESwat */
  527.                     if( pen==sprite->shadow_pen ) dest[x] = shade_table[dest[x]];
  528.                     else if( pen ) dest[x] = pal_data[pen];
  529.                     xcount += sprite->tile_width;
  530.                 }
  531. skip5:
  532.                 ycount += sprite->tile_height;
  533.                 dest += pitch;
  534.             }
  535.         }
  536.     }
  537.     else
  538.     {    // Shadow Sprite
  539.         const unsigned char *pen_data = sprite->pen_data;
  540. //        const unsigned short *pal_data = sprite->pal_data;
  541.         int x,y;
  542.         unsigned char pen;
  543.         int pitch = blit.line_offset*dy;
  544.         unsigned char *dest = blit.baseaddr + blit.line_offset*y1;
  545.         int ycount = ycount0;
  546.  
  547.         if( orientation & ORIENTATION_SWAP_XY ){ /* manually rotate the sprite graphics */
  548.             int xcount = xcount0;
  549.             for( x=x1; x!=x2; x+=dx ){
  550.                 const unsigned char *source;
  551.                 unsigned char *dest1;
  552.  
  553.                 ycount = ycount0;
  554.                 while( xcount>=sprite->total_width ){
  555.                     xcount -= sprite->total_width;
  556.                     pen_data+=sprite->line_offset;
  557.                 }
  558.                 source = pen_data;
  559.                 dest1 = &dest[x];
  560.                 for( y=y1; y!=y2; y+=dy ){
  561.                     while( ycount>=sprite->total_height ){
  562.                         ycount -= sprite->total_height;
  563.                         source ++;
  564.                     }
  565.                     pen = *source;
  566.                     if( pen==0xff ) goto skip4; /* marker for right side of sprite; needed for AltBeast, ESwat */
  567.                     if( pen ) *dest1 = shade_table[*dest1];
  568.                     ycount+= sprite->tile_height;
  569.                     dest1 += pitch;
  570.                 }
  571. skip4:
  572.                 xcount += sprite->tile_width;
  573.             }
  574.         }
  575.         else {
  576.             for( y=y1; y!=y2; y+=dy ){
  577.                 int xcount = xcount0;
  578.                 const unsigned char *source;
  579.                 while( ycount>=sprite->total_height ){
  580.                     ycount -= sprite->total_height;
  581.                     pen_data += sprite->line_offset;
  582.                 }
  583.                 source = pen_data;
  584.                 for( x=x1; x!=x2; x+=dx ){
  585.                     while( xcount>=sprite->total_width ){
  586.                         xcount -= sprite->total_width;
  587.                         source++;
  588.                     }
  589.                     pen = *source;
  590.                     if( pen==0xff ) goto skip3; /* marker for right side of sprite; needed for AltBeast, ESwat */
  591.                     if( pen ) dest[x] = shade_table[dest[x]];
  592.                     xcount += sprite->tile_width;
  593.                 }
  594. skip3:
  595.                 ycount += sprite->tile_height;
  596.                 dest += pitch;
  597.             }
  598.         }
  599.     }
  600.  
  601. }
  602.  
  603.  
  604. static void do_blit_zoom16( const struct sprite *sprite ){
  605.     /*    assumes SPRITE_LIST_RAW_DATA flag is set */
  606.  
  607.     int x1,x2, y1,y2, dx,dy;
  608.     int xcount0 = 0, ycount0 = 0;
  609.  
  610.     if( sprite->flags & SPRITE_FLIPX ){
  611.         x2 = sprite->x;
  612.         x1 = x2+sprite->total_width;
  613.         dx = -1;
  614.         if( x2<blit.clip_left ) x2 = blit.clip_left;
  615.         if( x1>blit.clip_right ){
  616.             xcount0 = (x1-blit.clip_right)*sprite->tile_width;
  617.             x1 = blit.clip_right;
  618.         }
  619.         if( x2>=x1 ) return;
  620.         x1--; x2--;
  621.     }
  622.     else {
  623.         x1 = sprite->x;
  624.         x2 = x1+sprite->total_width;
  625.         dx = 1;
  626.         if( x1<blit.clip_left ){
  627.             xcount0 = (blit.clip_left-x1)*sprite->tile_width;
  628.             x1 = blit.clip_left;
  629.         }
  630.         if( x2>blit.clip_right ) x2 = blit.clip_right;
  631.         if( x1>=x2 ) return;
  632.     }
  633.     if( sprite->flags & SPRITE_FLIPY ){
  634.         y2 = sprite->y;
  635.         y1 = y2+sprite->total_height;
  636.         dy = -1;
  637.         if( y2<blit.clip_top ) y2 = blit.clip_top;
  638.         if( y1>blit.clip_bottom ){
  639.             ycount0 = (y1-blit.clip_bottom)*sprite->tile_height;
  640.             y1 = blit.clip_bottom;
  641.         }
  642.         if( y2>=y1 ) return;
  643.         y1--; y2--;
  644.     }
  645.     else {
  646.         y1 = sprite->y;
  647.         y2 = y1+sprite->total_height;
  648.         dy = 1;
  649.         if( y1<blit.clip_top ){
  650.             ycount0 = (blit.clip_top-y1)*sprite->tile_height;
  651.             y1 = blit.clip_top;
  652.         }
  653.         if( y2>blit.clip_bottom ) y2 = blit.clip_bottom;
  654.         if( y1>=y2 ) return;
  655.     }
  656.  
  657.     if(!(sprite->flags & (SPRITE_SHADOW | SPRITE_PARTIAL_SHADOW)))
  658.     {
  659.         const unsigned char *pen_data = sprite->pen_data;
  660.         const unsigned short *pal_data = sprite->pal_data;
  661.         int x,y;
  662.         unsigned char pen;
  663.         int pitch = blit.line_offset*dy/2;
  664.         UINT16 *dest = (UINT16 *)(blit.baseaddr + blit.line_offset*y1);
  665.         int ycount = ycount0;
  666.  
  667.         if( orientation & ORIENTATION_SWAP_XY ){ /* manually rotate the sprite graphics */
  668.             int xcount = xcount0;
  669.             for( x=x1; x!=x2; x+=dx ){
  670.                 const unsigned char *source;
  671.                 UINT16 *dest1;
  672.  
  673.                 ycount = ycount0;
  674.                 while( xcount>=sprite->total_width ){
  675.                     xcount -= sprite->total_width;
  676.                     pen_data+=sprite->line_offset;
  677.                 }
  678.                 source = pen_data;
  679.                 dest1 = &dest[x];
  680.                 for( y=y1; y!=y2; y+=dy ){
  681.                     while( ycount>=sprite->total_height ){
  682.                         ycount -= sprite->total_height;
  683.                         source ++;
  684.                     }
  685.                     pen = *source;
  686.                     if( pen==0xff ) goto skip1; /* marker for right side of sprite; needed for AltBeast, ESwat */
  687. /*                    if( pen==10 ) *dest1 = shade_table[*dest1];
  688.                     else */if( pen ) *dest1 = pal_data[pen];
  689.                     ycount+= sprite->tile_height;
  690.                     dest1 += pitch;
  691.                 }
  692. skip1:
  693.                 xcount += sprite->tile_width;
  694.             }
  695.         }
  696.         else {
  697.             for( y=y1; y!=y2; y+=dy ){
  698.                 int xcount = xcount0;
  699.                 const unsigned char *source;
  700.                 while( ycount>=sprite->total_height ){
  701.                     ycount -= sprite->total_height;
  702.                     pen_data += sprite->line_offset;
  703.                 }
  704.                 source = pen_data;
  705.                 for( x=x1; x!=x2; x+=dx ){
  706.                     while( xcount>=sprite->total_width ){
  707.                         xcount -= sprite->total_width;
  708.                         source++;
  709.                     }
  710.                     pen = *source;
  711.                     if( pen==0xff ) goto skip; /* marker for right side of sprite; needed for AltBeast, ESwat */
  712. /*                    if( pen==10 ) dest[x] = shade_table[dest[x]];
  713.                     else */if( pen ) dest[x] = pal_data[pen];
  714.                     xcount += sprite->tile_width;
  715.                 }
  716. skip:
  717.                 ycount += sprite->tile_height;
  718.                 dest += pitch;
  719.             }
  720.         }
  721.     }
  722.     else if(sprite->flags & SPRITE_PARTIAL_SHADOW)
  723.     {
  724.         const unsigned char *pen_data = sprite->pen_data;
  725.         const unsigned short *pal_data = sprite->pal_data;
  726.         int x,y;
  727.         unsigned char pen;
  728.         int pitch = blit.line_offset*dy/2;
  729.         UINT16 *dest = (UINT16 *)(blit.baseaddr + blit.line_offset*y1);
  730.         int ycount = ycount0;
  731.  
  732.         if( orientation & ORIENTATION_SWAP_XY ){ /* manually rotate the sprite graphics */
  733.             int xcount = xcount0;
  734.             for( x=x1; x!=x2; x+=dx ){
  735.                 const unsigned char *source;
  736.                 UINT16 *dest1;
  737.  
  738.                 ycount = ycount0;
  739.                 while( xcount>=sprite->total_width ){
  740.                     xcount -= sprite->total_width;
  741.                     pen_data+=sprite->line_offset;
  742.                 }
  743.                 source = pen_data;
  744.                 dest1 = &dest[x];
  745.                 for( y=y1; y!=y2; y+=dy ){
  746.                     while( ycount>=sprite->total_height ){
  747.                         ycount -= sprite->total_height;
  748.                         source ++;
  749.                     }
  750.                     pen = *source;
  751.                     if( pen==0xff ) goto skip6; /* marker for right side of sprite; needed for AltBeast, ESwat */
  752.                     if( pen==sprite->shadow_pen ) *dest1 = shade_table[*dest1];
  753.                     else if( pen ) *dest1 = pal_data[pen];
  754.                     ycount+= sprite->tile_height;
  755.                     dest1 += pitch;
  756.                 }
  757. skip6:
  758.                 xcount += sprite->tile_width;
  759.             }
  760.         }
  761.         else {
  762.             for( y=y1; y!=y2; y+=dy ){
  763.                 int xcount = xcount0;
  764.                 const unsigned char *source;
  765.                 while( ycount>=sprite->total_height ){
  766.                     ycount -= sprite->total_height;
  767.                     pen_data += sprite->line_offset;
  768.                 }
  769.                 source = pen_data;
  770.                 for( x=x1; x!=x2; x+=dx ){
  771.                     while( xcount>=sprite->total_width ){
  772.                         xcount -= sprite->total_width;
  773.                         source++;
  774.                     }
  775.                     pen = *source;
  776.                     if( pen==0xff ) goto skip5; /* marker for right side of sprite; needed for AltBeast, ESwat */
  777.                     if( pen==sprite->shadow_pen ) dest[x] = shade_table[dest[x]];
  778.                     else if( pen ) dest[x] = pal_data[pen];
  779.                     xcount += sprite->tile_width;
  780.                 }
  781. skip5:
  782.                 ycount += sprite->tile_height;
  783.                 dest += pitch;
  784.             }
  785.         }
  786.     }
  787.     else
  788.     {    // Shadow Sprite
  789.         const unsigned char *pen_data = sprite->pen_data;
  790. //        const unsigned short *pal_data = sprite->pal_data;
  791.         int x,y;
  792.         unsigned char pen;
  793.         int pitch = blit.line_offset*dy/2;
  794.         UINT16 *dest = (UINT16 *)(blit.baseaddr + blit.line_offset*y1);
  795.         int ycount = ycount0;
  796.  
  797.         if( orientation & ORIENTATION_SWAP_XY ){ /* manually rotate the sprite graphics */
  798.             int xcount = xcount0;
  799.             for( x=x1; x!=x2; x+=dx ){
  800.                 const unsigned char *source;
  801.                 UINT16 *dest1;
  802.  
  803.                 ycount = ycount0;
  804.                 while( xcount>=sprite->total_width ){
  805.                     xcount -= sprite->total_width;
  806.                     pen_data+=sprite->line_offset;
  807.                 }
  808.                 source = pen_data;
  809.                 dest1 = &dest[x];
  810.                 for( y=y1; y!=y2; y+=dy ){
  811.                     while( ycount>=sprite->total_height ){
  812.                         ycount -= sprite->total_height;
  813.                         source ++;
  814.                     }
  815.                     pen = *source;
  816.                     if( pen==0xff ) goto skip4; /* marker for right side of sprite; needed for AltBeast, ESwat */
  817.                     if( pen ) *dest1 = shade_table[*dest1];
  818.                     ycount+= sprite->tile_height;
  819.                     dest1 += pitch;
  820.                 }
  821. skip4:
  822.                 xcount += sprite->tile_width;
  823.             }
  824.         }
  825.         else {
  826.             for( y=y1; y!=y2; y+=dy ){
  827.                 int xcount = xcount0;
  828.                 const unsigned char *source;
  829.                 while( ycount>=sprite->total_height ){
  830.                     ycount -= sprite->total_height;
  831.                     pen_data += sprite->line_offset;
  832.                 }
  833.                 source = pen_data;
  834.                 for( x=x1; x!=x2; x+=dx ){
  835.                     while( xcount>=sprite->total_width ){
  836.                         xcount -= sprite->total_width;
  837.                         source++;
  838.                     }
  839.                     pen = *source;
  840.                     if( pen==0xff ) goto skip3; /* marker for right side of sprite; needed for AltBeast, ESwat */
  841.                     if( pen ) dest[x] = shade_table[dest[x]];
  842.                     xcount += sprite->tile_width;
  843.                 }
  844. skip3:
  845.                 ycount += sprite->tile_height;
  846.                 dest += pitch;
  847.             }
  848.         }
  849.     }
  850.  
  851. }
  852.  
  853. /*********************************************************************/
  854.  
  855. void sprite_init( void ){
  856.     const struct rectangle *clip = &Machine->drv->visible_area;
  857.     int left = clip->min_x;
  858.     int top = clip->min_y;
  859.     int right = clip->max_x+1;
  860.     int bottom = clip->max_y+1;
  861.  
  862.     struct osd_bitmap *bitmap = Machine->scrbitmap;
  863.     screen_baseaddr = bitmap->line[0];
  864.     screen_line_offset = bitmap->line[1]-bitmap->line[0];
  865.  
  866.     orientation = Machine->orientation;
  867.     screen_width = Machine->scrbitmap->width;
  868.     screen_height = Machine->scrbitmap->height;
  869.  
  870.     if( orientation & ORIENTATION_SWAP_XY ){
  871.         SWAP(left,top)
  872.         SWAP(right,bottom)
  873.     }
  874.     if( orientation & ORIENTATION_FLIP_X ){
  875.         SWAP(left,right)
  876.         left = screen_width-left;
  877.         right = screen_width-right;
  878.     }
  879.     if( orientation & ORIENTATION_FLIP_Y ){
  880.         SWAP(top,bottom)
  881.         top = screen_height-top;
  882.         bottom = screen_height-bottom;
  883.     }
  884.  
  885.     screen_clip_left = left;
  886.     screen_clip_right = right;
  887.     screen_clip_top = top;
  888.     screen_clip_bottom = bottom;
  889. }
  890.  
  891. void sprite_close( void ){
  892.     struct sprite_list *sprite_list = first_sprite_list;
  893.     mask_buffer_dispose();
  894.  
  895.     while( sprite_list ){
  896.         struct sprite_list *next = sprite_list->next;
  897.         free( sprite_list->sprite );
  898.         free( sprite_list );
  899.         sprite_list = next;
  900.     }
  901.     first_sprite_list = NULL;
  902. }
  903.  
  904. struct sprite_list *sprite_list_create( int num_sprites, int flags ){
  905.     struct sprite *sprite = calloc( num_sprites, sizeof(struct sprite) );
  906.     struct sprite_list *sprite_list = calloc( 1, sizeof(struct sprite_list) );
  907.  
  908.     sprite_list->num_sprites = num_sprites;
  909.     sprite_list->special_pen = -1;
  910.     sprite_list->sprite = sprite;
  911.     sprite_list->flags = flags;
  912.  
  913.     /* resource tracking */
  914.     sprite_list->next = first_sprite_list;
  915.     first_sprite_list = sprite_list;
  916.  
  917.     return sprite_list; /* warning: no error checking! */
  918. }
  919.  
  920. static void sprite_update_helper( struct sprite_list *sprite_list ){
  921.     struct sprite *sprite_table = sprite_list->sprite;
  922.  
  923.     /* initialize constants */
  924.     blit.transparent_pen = sprite_list->transparent_pen;
  925.     blit.write_to_mask = 1;
  926.     blit.clip_left = 0;
  927.     blit.clip_top = 0;
  928.  
  929.     /* make a pass to adjust for screen orientation */
  930.     if( orientation & ORIENTATION_SWAP_XY ){
  931.         struct sprite *sprite = sprite_table;
  932.         const struct sprite *finish = &sprite[sprite_list->num_sprites];
  933.         while( sprite<finish ){
  934.             SWAP(sprite->x, sprite->y)
  935.             SWAP(sprite->total_height,sprite->total_width)
  936.             SWAP(sprite->tile_width,sprite->tile_height)
  937.             SWAP(sprite->x_offset,sprite->y_offset)
  938.  
  939.             /* we must also swap the flipx and flipy bits (if they aren't identical) */
  940.             if( sprite->flags&SPRITE_FLIPX ){
  941.                 if( !(sprite->flags&SPRITE_FLIPY) ){
  942.                     sprite->flags = (sprite->flags&~SPRITE_FLIPX)|SPRITE_FLIPY;
  943.                 }
  944.             }
  945.             else {
  946.                 if( sprite->flags&SPRITE_FLIPY ){
  947.                     sprite->flags = (sprite->flags&~SPRITE_FLIPY)|SPRITE_FLIPX;
  948.                 }
  949.             }
  950.             sprite++;
  951.         }
  952.     }
  953.     if( orientation & ORIENTATION_FLIP_X ){
  954.         struct sprite *sprite = sprite_table;
  955.         const struct sprite *finish = &sprite[sprite_list->num_sprites];
  956. #ifndef PREROTATE_GFX
  957.         int toggle_bit = SPRITE_FLIPX;
  958. #else
  959.         int toggle_bit = (sprite_list->flags & SPRITE_LIST_RAW_DATA)?SPRITE_FLIPX:0;
  960. #endif
  961.         while( sprite<finish ){
  962.             sprite->x = screen_width - (sprite->x+sprite->total_width);
  963.             sprite->flags ^= toggle_bit;
  964.  
  965.             /* extra processing for packed sprites */
  966.             sprite->x_offset = sprite->tile_width - (sprite->x_offset+sprite->total_width);
  967.             sprite++;
  968.         }
  969.     }
  970.     if( orientation & ORIENTATION_FLIP_Y ){
  971.         struct sprite *sprite = sprite_table;
  972.         const struct sprite *finish = &sprite[sprite_list->num_sprites];
  973. #ifndef PREROTATE_GFX
  974.         int toggle_bit = SPRITE_FLIPY;
  975. #else
  976.         int toggle_bit = (sprite_list->flags & SPRITE_LIST_RAW_DATA)?SPRITE_FLIPY:0;
  977. #endif
  978.         while( sprite<finish ){
  979.             sprite->y = screen_height - (sprite->y+sprite->total_height);
  980.             sprite->flags ^= toggle_bit;
  981.  
  982.             /* extra processing for packed sprites */
  983.             sprite->y_offset = sprite->tile_height - (sprite->y_offset+sprite->total_height);
  984.             sprite++;
  985.         }
  986.     }
  987.     { /* visibility check */
  988.         struct sprite *sprite = sprite_table;
  989.         const struct sprite *finish = &sprite[sprite_list->num_sprites];
  990.         while( sprite<finish ){
  991.             if( (FlickeringInvisible && (sprite->flags & SPRITE_FLICKER)) ||
  992.                 sprite->total_width<=0 || sprite->total_height<=0 ||
  993.                 sprite->x + sprite->total_width<=0 || sprite->x>=screen_width ||
  994.                 sprite->y + sprite->total_height<=0 || sprite->y>=screen_height ){
  995.                 sprite->flags &= (~SPRITE_VISIBLE);
  996.             }
  997.             sprite++;
  998.         }
  999.     }
  1000.     {
  1001.         int j,i, dir, last;
  1002.         void (*do_blit)( const struct sprite * );
  1003.  
  1004.         switch( sprite_list->sprite_type ){
  1005.             case SPRITE_TYPE_ZOOM:
  1006.             do_blit = do_blit_zoom;
  1007.             return;
  1008.             break;
  1009.  
  1010.             case SPRITE_TYPE_STACK:
  1011.             do_blit = do_blit_stack;
  1012.             break;
  1013.  
  1014.             case SPRITE_TYPE_UNPACK:
  1015.             default:
  1016.             do_blit = do_blit_unpack;
  1017.             break;
  1018.         }
  1019.  
  1020.         sprite_order_setup( sprite_list, &i, &last, &dir );
  1021.  
  1022.         for(;;){ /* process each sprite */
  1023.             struct sprite *sprite = &sprite_table[i];
  1024.             sprite->mask_offset = -1;
  1025.  
  1026.             if( sprite->flags & SPRITE_VISIBLE ){
  1027.                 int priority = sprite->priority;
  1028.  
  1029.                 if( palette_used_colors ){
  1030.                     UINT32 pen_usage = sprite->pen_usage;
  1031.                     int indx = sprite->pal_data - Machine->remapped_colortable;
  1032.                     while( pen_usage ){
  1033.                         if( pen_usage&1 ) palette_used_colors[indx] = PALETTE_COLOR_USED;
  1034.                         pen_usage>>=1;
  1035.                         indx++;
  1036.                     }
  1037.                 }
  1038.  
  1039.                 if( i!=last && priority<sprite_list->max_priority ){
  1040.                     blit.origin_x = sprite->x;
  1041.                     blit.origin_y = sprite->y;
  1042.                     /* clip_left and clip_right are always zero */
  1043.                     blit.clip_right = sprite->total_width;
  1044.                     blit.clip_bottom = sprite->total_height;
  1045.                 /*
  1046.                     The following loop ensures that even though we are drawing all priority 3
  1047.                     sprites before drawing the priority 2 sprites, and priority 2 sprites before the
  1048.                     priority 1 sprites, that the sprite order as a whole still dictates
  1049.                     sprite-to-sprite priority when sprite pixels overlap and aren't obscured by a
  1050.                     background.  Checks are done to avoid special handling for the cases where
  1051.                     masking isn't needed.
  1052.  
  1053.                     max priority sprites are always drawn first, so we don't need to do anything
  1054.                     special to cause them to be obscured by other sprites
  1055.                 */
  1056.                     j = i+dir;
  1057.                     for(;;){
  1058.                         struct sprite *front = &sprite_table[j];
  1059.                         if( (front->flags&SPRITE_VISIBLE) && front->priority>priority ){
  1060.  
  1061.                             if( front->x < sprite->x+sprite->total_width &&
  1062.                                 front->y < sprite->y+sprite->total_height &&
  1063.                                 front->x+front->total_width > sprite->x &&
  1064.                                 front->y+front->total_height > sprite->y )
  1065.                             {
  1066.                                 /* uncomment the following line to see which sprites are corrected */
  1067.                                 //sprite->pal_data = Machine->remapped_colortable+(rand()&0xff);
  1068.  
  1069.                                 if( sprite->mask_offset<0 ){ /* first masking? */
  1070.                                     sprite->mask_offset = mask_buffer_alloc( sprite->total_width * sprite->total_height );
  1071.                                     blit.line_offset = sprite->total_width;
  1072.                                     blit.baseaddr = &mask_buffer[sprite->mask_offset];
  1073.                                 }
  1074.                                 do_blit( front );
  1075.                             }
  1076.                         }
  1077.                         if( j==last ) break;
  1078.                         j += dir;
  1079.                     } /* next j */
  1080.                 } /* priority<SPRITE_MAX_PRIORITY */
  1081.             } /* visible */
  1082.             if( i==last ) break;
  1083.             i += dir;
  1084.         } /* next i */
  1085.     }
  1086. }
  1087.  
  1088. void sprite_update( void ){
  1089.     struct sprite_list *sprite_list = first_sprite_list;
  1090.     mask_buffer_reset();
  1091.     FlickeringInvisible = !FlickeringInvisible;
  1092.     while( sprite_list ){
  1093.         sprite_update_helper( sprite_list );
  1094.         sprite_list = sprite_list->next;
  1095.     }
  1096. }
  1097.  
  1098. void sprite_draw( struct sprite_list *sprite_list, int priority ){
  1099.     const struct sprite *sprite_table = sprite_list->sprite;
  1100.  
  1101.  
  1102.     { /* set constants */
  1103.         blit.origin_x = 0;
  1104.         blit.origin_y = 0;
  1105.  
  1106.         blit.baseaddr = screen_baseaddr;
  1107.         blit.line_offset = screen_line_offset;
  1108.         blit.transparent_pen = sprite_list->transparent_pen;
  1109.         blit.write_to_mask = 0;
  1110.  
  1111.         blit.clip_left = screen_clip_left;
  1112.         blit.clip_top = screen_clip_top;
  1113.         blit.clip_right = screen_clip_right;
  1114.         blit.clip_bottom = screen_clip_bottom;
  1115.     }
  1116.  
  1117.     {
  1118.         int i, dir, last;
  1119.         void (*do_blit)( const struct sprite * );
  1120.  
  1121.         switch( sprite_list->sprite_type ){
  1122.             case SPRITE_TYPE_ZOOM:
  1123.             if (Machine->scrbitmap->depth == 16) /* 16 bit */
  1124.             {
  1125.                 do_blit = do_blit_zoom16;
  1126. //                return;
  1127.             }
  1128.             else
  1129.                 do_blit = do_blit_zoom;
  1130.             break;
  1131.  
  1132.             case SPRITE_TYPE_STACK:
  1133.             do_blit = do_blit_stack;
  1134.             break;
  1135.  
  1136.             case SPRITE_TYPE_UNPACK:
  1137.             default:
  1138.             do_blit = do_blit_unpack;
  1139.             break;
  1140.         }
  1141.  
  1142.         sprite_order_setup( sprite_list, &i, &last, &dir );
  1143.         for(;;){
  1144.             const struct sprite *sprite = &sprite_table[i];
  1145.             if( (sprite->flags&SPRITE_VISIBLE) && (sprite->priority==priority) ) do_blit( sprite );
  1146.             if( i==last ) break;
  1147.             i+=dir;
  1148.         }
  1149.     }
  1150. }
  1151.  
  1152.  
  1153. void sprite_set_shade_table(UINT16 *table)
  1154. {
  1155.     shade_table=table;
  1156. }
  1157.